

import {
  BleDscpUtils
} from "../../utils/BleDscpUtils"
let bleDscpUtils = new BleDscpUtils();
import {
  ProtocolUtils
} from "../..//utils/ProtocolUtils";
let protocolUtils = new ProtocolUtils();
import {
  ByteUtils
} from '../../../common/utils/ByteUtils';
let byteUtils = new ByteUtils();
let DscpCode = require('./DscpCode')

class PersonalLockOperate {
  // 会话码：生成类时会随机生成，调用setSessionCode时，也会重新生成
  sessionCode;

  constructor() {
    if (!PersonalLockOperate.instance) {
      console.log("PersonalLockOperate实例创建成功")
      PersonalLockOperate.instance = this;
    }
    return PersonalLockOperate.instance;
  }

  /**
 * 连接握手
 * 0x5C,0x5F,0x57,0x59,0x5E （固定）
 */
  connectHand(callback) {
    let sendCmdData = Array()
    sendCmdData.push(0x5C)
    sendCmdData.push(0x5F)
    sendCmdData.push(0x57)
    sendCmdData.push(0x59)
    sendCmdData.push(0x5E)
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      console.log("收到握手回复")
      let obj = new Object();
      obj.isSucceed = recvCmdData[0] == 2 ? true : false; // true设置成功
      obj.errCode = recvCmdData[0] == 0 ? 0xFF : recvCmdData[0];
      callback(true, obj);
    }, DscpCode.CONNECT_HAND, sendCmdData);
  }

  /**
* 开锁1
* 0x00,0x00,0x01,0x00,0x00 （固定）
*/
  openLock(callback, lockIndex) {
    let sendCmdData = Array()
    sendCmdData.push(0x00)
    sendCmdData.push(0x00)
    sendCmdData.push(lockIndex)
    sendCmdData.push(0x00)
    sendCmdData.push(0x00)
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      let obj = new Object();
      obj.isSucceed = recvCmdData[0] == 3 ? true : false; // true设置成功
      obj.errCode = recvCmdData[0] == 0 ? 0xFF : recvCmdData[0];
      callback(true, obj);
    }, DscpCode.OPEN_LOCK, sendCmdData);
  }

  /**
* 打开所有锁
* 0xB1,0xB2,0xB3,0xB4,0xB5 （固定）
*/
  openAllLock(callback) {
    let sendCmdData = Array()
    sendCmdData.push(0xB1)
    sendCmdData.push(0xB2)
    sendCmdData.push(0xB3)
    sendCmdData.push(0xB4)
    sendCmdData.push(0xB5)
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      let obj = new Object();
      obj.isSucceed = recvCmdData[0] == 3 ? true : false; // true设置成功
      callback(true, obj);
    }, DscpCode.OPEN_ALL_LOCK, sendCmdData);
  }

  /**
* 获取电量
* 实际电压 （0X42:3.3V，   0X46:3.5V，0X50:3.6V,   0X54:3.7V,    0X58:3.8V  ,0X62:4V）
*/
  getBatteryVoc(callback) {
    let sendCmdData = Array()
    sendCmdData.push(0x00)
    sendCmdData.push(0x00)
    sendCmdData.push(0x00)
    sendCmdData.push(0x00)
    sendCmdData.push(0x00)
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return; 
      }
      let obj = new Object();
      obj.isSucceed = recvCmdData[0] != 0 ? true : false; // true设置成功
      if (recvCmdData[0] <= 0x42) {
        obj.voc = 3.3
      } else if (recvCmdData[0] <= 0x46) {
        obj.voc = 3.5
      } else if (recvCmdData[0] <= 0x50) {
        obj.voc = 3.6
      } else if (recvCmdData[0] <= 0x54) {
        obj.voc = 3.7
      } else if (recvCmdData[0] <= 0x58) {
        obj.voc = 3.8
      } else {
        obj.voc = 4
      }
      obj.errCode = recvCmdData[0] == 0 ? 0xFF : recvCmdData[0];
      callback(true, obj);
    }, DscpCode.GET_BATTERY_VOC, sendCmdData);
  }

  /**
   * 设置会话码
   * 输入参数：
   * 时间戳 6byte + 
   * 会话码 8byte + 
   * 1Byte 发送方：1：手机端 2：网关
   * 4Byte 用户ID
   * 输出参数：
   * 1Byte 0：成功 1：失败	
   * 1Byte 锁开关状态 0：关 1：开	
   * 4Byte 已注册：用户ID 未注册：全填0xFF
   * 8Byte 会话码
   * 1Byte 上次连接断开原因
   * 1Byte 蓝牙最大传输单元MTU
   */
  setSessionCode(callback, way, userId) {
    let curTime = protocolUtils.getTimeArray(Date());
    this.sessionCode = byteUtils.getRandomBytes(8, 255);
    let sendCmdData = curTime.concat(this.sessionCode);
    if (way) {
      sendCmdData.push(way)
    } else {
      sendCmdData.push(1)
    }
    sendCmdData = sendCmdData.concat(protocolUtils.getUserIdArray(userId))
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      let obj = new Object();
      obj.isSucceed = recvCmdData[0] == 0 ? true : false; // true设置成功
      obj.isLocked = recvCmdData[1] == 0; // 0 关 1 开
      obj.userId = byteUtils.bytes2ToInt(recvCmdData.slice(2, 6));
      obj.sessionCode = recvCmdData.slice(6, 14);
      obj.lastDisconnectCode = recvCmdData[14];
      obj.bleMTU = recvCmdData[15];
      callback(true, obj);
    }, DscpCode.SET_SESSION_CODE, sendCmdData);
  }

  /**
    * 设置出厂信息
    * 输入参数：
    * 时间戳 6byte
    * harwareVersion: 硬件版本号 4byte
    * softwareVersion： 软件版本号 4byte
    * sn: 设备SN号  16byte
    * typeCodeArray: 设备类型编号 2byte
    * localName: 蓝牙广播中的LocalName-即蓝牙名称-20byte
    * companyCode: Manufacturer 中的前两位-2byte 默认为0xFF7E
    * deviceSupport：设备功能支持-2byte
    * bleServiceUuid：蓝牙广播UUID字段-2byte 默认为0xFF7E
    * bleLogMode 是否记录蓝牙开光锁日志 0：不记录 1：记录
    * ipPort: ip端口号
    * ip 地址长度 1Byte
    * ip: IP地址
    * 输出参数：
    * 1Byte 0成功 1失败
    * 返回ture设置成功，返回false设置失败
    */
  setFactoryInfo(date, harwareVersion, softwareVersion, sn,
    typeCodeArray, localName, deviceSupport, bleLogMode,
    bleBroadcastInterval, spare1, spare2,
    ipPort, ip, callback) {
    console.log("------设置出厂信息------")
    let sendCmdData = new Array();
    console.log("时间 = " + protocolUtils.getTimeArray(date))
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(date));
    console.log("硬件版本 = " + protocolUtils.getVersionBytes(harwareVersion))
    sendCmdData = sendCmdData.concat(protocolUtils.getVersionBytes(harwareVersion))
    console.log("软件版本 = " + protocolUtils.getVersionBytes(softwareVersion))
    sendCmdData = sendCmdData.concat(protocolUtils.getVersionBytes(softwareVersion))
    console.log("SN Byte = " + byteUtils.ab2hex(sn))
    sendCmdData = sendCmdData.concat(sn);
    console.log("类型编码 = " + typeCodeArray)
    sendCmdData = sendCmdData.concat(typeCodeArray);
    let localNameBytes = byteUtils.strToAsciiBytes(localName);
    if (localNameBytes.length <= 0 || localNameBytes.length > 20) {
      console.log("------蓝牙名称长度超过限制------")
      my.showToast({
        content: '蓝牙名称长度超过限制',
        icon: 'none',
      });
      return;
    }
    while (localNameBytes.length < 20) {
      localNameBytes.push(0);
    }
    console.log("蓝牙字符串 = " + localNameBytes)
    console.log("蓝牙名称Byte = " + byteUtils.ab2hex(localNameBytes))
    sendCmdData = sendCmdData.concat(localNameBytes);
    console.log("公司标识 = " + byteUtils.ab2hex([0xff, 0x7e]))
    sendCmdData = sendCmdData.concat([0xff, 0x7e]);
    console.log("功能支持 = " + byteUtils.ab2hex(deviceSupport))
    sendCmdData = sendCmdData.concat(deviceSupport)
    console.log("广播UUID = " + byteUtils.ab2hex([0xff, 0x7e]))
    sendCmdData = sendCmdData.concat([0xff, 0x7e])
    console.log("蓝牙日志模式 = " + bleLogMode)
    sendCmdData.push(bleLogMode);
    console.log("蓝牙广播间隔 = " + bleBroadcastInterval)
    sendCmdData.push(bleBroadcastInterval);
    sendCmdData.push(spare1);
    sendCmdData.push(spare2);
    console.log(sendCmdData.length)
    console.log("IP端口 = " + ipPort)
    sendCmdData = sendCmdData.concat(byteUtils.intToBytes2(ipPort));
    console.log("ip长度 = " + ip.length)
    sendCmdData.push(ip.length);
    console.log("ip = " + ip)
    console.log("ip Byte = " + byteUtils.ab2hex(byteUtils.strToAsciiBytes(ip)));
    sendCmdData = sendCmdData.concat(byteUtils.strToAsciiBytes(ip))
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      callback(true, recvCmdData[0] == 0);
      // 返回ture设置成功，返回false设置失败
    }, DscpCode.SET_FACTORY_INFO, sendCmdData);
  }

  /**
   * 设置NB初始化参数
   * 输入参数：
   * 时间戳 6byte
   * nbType: NB频段设置 0：全频段 1：电信 2：移动，联通
   * iotIp: iot平台Ip地址
   * nbLightConfig: NB 联网灯光配置 0：开启 1：关闭
   * nbCtrlWorkMode: NB控制器工作模式 0：低功耗 1：eDRX 2：DRX
   * eDRXPagingCycle: eDRX寻呼周期 1Byte
   * eDRXCycle: eDRX周期 1Byte
   * nbBaudRate: NB模组波特率设置 0：9600 1：57600 2：115200
   * 输出参数：
   * 1Byte 0成功 1失败
   * 返回ture设置成功，返回false设置失败
   */
  setNbInitInfo(date, nbType, iotIp, nbLightConfig, nbCtrlWorkMode,
    eDRXPagingCycle, eDRXCycle, nbBaudRate) {
    let sendCmdData = new Array();
    let timestamp = protocolUtils.getTimeArray(date);
    sendCmdData = sendCmdData.concat(timestamp);
    sendCmdData.push(nbType);
    let ipArray = byteUtils.strToAsciiBytes(iotIp);
    sendCmdData.push(ipArray.length);
    sendCmdData = sendCmdData.concat(ipArray);
    sendCmdData.push(nbLightConfig);
    sendCmdData.push(nbCtrlWorkMode);
    sendCmdData.push(eDRXPagingCycle);
    sendCmdData.push(eDRXCycle);
    sendCmdData.push(nbBaudRate);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      console.log(recvCmdData)
      callback(true, (recvCmdData[0] & 0x0F) == 0, recvCmdData[0]);
      // 返回ture设置成功，返回false设置失败
    }, DscpCode.SET_NB_INIT_INFO, sendCmdData);
  }

  /**
   * 获取NB联网信息参数
   * 输入参数：
   * 输出参数：
   * 1Byte 0成功 1失败
   * 返回ture设置成功，返回false设置失败
   */
  getNbNetInfo(callback) {
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      let obj = new Object();
      obj.time = protocolUtils.getTimeByArray(recvCmdData.slice(0, 6));//时间戳
      obj.imei = byteUtils.bytesToAsciiStr(recvCmdData.slice(6, 21));
      obj.imsi = byteUtils.bytesToAsciiStr(recvCmdData.slice(21, 36));
      obj.rsrp = byteUtils.bytes2ToInt(recvCmdData.slice(36, 38));
      obj.snr = byteUtils.bytes2ToInt(recvCmdData.slice(38, 40));
      obj.pci = byteUtils.bytesToAsciiStr(recvCmdData.slice(40, 43));
      obj.nbBand = recvCmdData[43];
      obj.ipLength = recvCmdData[44];
      if (obj.ipLength > 0) {
        obj.ip = byteUtils.bytesToAsciiStr(recvCmdData.slice(45, 45 + obj.ipLength));
      } else {
        obj.ip = "";
      }
      let curIndex = 45 + obj.length;
      obj.nbLightConfig = recvCmdData[curIndex];
      obj.nbWorkMode = recvCmdData[curIndex + 1];
      obj.eDRXPagingCycle = recvCmdData[curIndex + 2];
      obj.eDRXCycle = recvCmdData[curIndex + 3];
      obj.nbBaudRate = recvCmdData[curIndex + 4];
      obj.pci = byteUtils.bytesToAsciiStr(recvCmdData.slice(curIndex + 5, curIndex + 5 + 9));
      callback(true, obj)
    }, DscpCode.GET_NB_NET_INGO, null);
  }

  /**
   * 注册设备
   * 输入参数：
   * timestamp: 时间戳 6byte
   * oprerateKey: 操作密钥 16byte
   * userId: 用户id 4byte
   * ipPort： IP端口号 2byte
   * 1Byte：IP地址的长度n
   * ip: ip地址
   * 输出参数：
   * 1Byte 0成功 1失败
   * 回调：
   * 返回ture设置成功，返回false设置失败
   */
  registerDevice(date, operateKey, userId,
    ipPort, ip, callback) {
    let sendCmdData = new Array();
    let timestamp = protocolUtils.getTimeArray(date);
    let userIdArray = protocolUtils.getUserIdArray(userId);
    let ipPortArray = byteUtils.intToBytes2(ipPort);
    let ipArray = byteUtils.strToAsciiBytes(ip);
    sendCmdData = sendCmdData.concat(timestamp,
      byteUtils.uuidToBytes(operateKey), userIdArray);
    sendCmdData.push(0x1);
    sendCmdData = sendCmdData.concat(ipPortArray);
    sendCmdData.push(ipArray.length);
    sendCmdData = sendCmdData.concat(ipArray);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      if ((recvCmdData[0] & 0x0F) == 0) {
        // 将设备设置成已注册状态
        bleDscpUtils.setDeviceRegisterStatus(true, operateKey);
      }
      console.log(recvCmdData)
      callback(true, (recvCmdData[0] & 0x0F) == 0, recvCmdData[0]);
      // 返回ture设置成功，返回false设置失败
    }, DscpCode.REGISTER_DEVICE, sendCmdData);
  }

  /**
   * 设备操作
   * 输入参数：
   * timestamp: 时间戳
   * operate: 1byte: 1：蓝牙被动开锁 2：上锁 3：清空设备 4：蓝牙预开锁命令
   * userId: 用户id 4byte
   * lockIndex: 锁具下标，从0开始
   * 输出参数：
   * 1Byte  0成功 1失败 2授权认证失败
   */
  operateNbDevice(date, operate, userId, lockIndex, callback) {
    let sendCmdData = new Array();
    let timestamp = protocolUtils.getTimeArray(date);
    let userIdArray = protocolUtils.getUserIdArray(userId);
    sendCmdData = sendCmdData.concat(timestamp);
    sendCmdData.push(operate);
    sendCmdData = sendCmdData.concat(userIdArray);
    sendCmdData.push(lockIndex);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      if (operate == 3 && (recvCmdData[0] & 0x0F) == 0) {
        // 将设备设置成未注册状态
        bleDscpUtils.setDeviceRegisterStatus(false);
      }
      callback(true, (recvCmdData[0] & 0x0F) == 0, recvCmdData[0]);
    }, DscpCode.OPERATE_DEVICE, sendCmdData);
  }

  /**
   * 设备操作
   * 输入参数：
   * timestamp: 时间戳
   * operate: 1byte: 1：蓝牙被动开锁 2：上锁 3：清空设备 4：蓝牙预开锁命令
   * userId: 用户id 4byte
   * 输出参数：
   * 1Byte  0成功 1失败 2授权认证失败
   */
  operateDevice(date, operate, userId, callback) {
    let sendCmdData = new Array();
    let timestamp = protocolUtils.getTimeArray(date);
    let userIdArray = protocolUtils.getUserIdArray(userId);
    sendCmdData = sendCmdData.concat(timestamp);
    sendCmdData.push(operate);
    sendCmdData = sendCmdData.concat(userIdArray);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      if (operate == 3 && (recvCmdData[0] & 0x0F) == 0) {
        // 将设备设置成未注册状态
        bleDscpUtils.setDeviceRegisterStatus(false);
      }
      callback(true, (recvCmdData[0] & 0x0F) == 0, recvCmdData[0]);
    }, DscpCode.OPERATE_DEVICE, sendCmdData);
  }

  /**
   * 设备升级
   */
  deviceUpgrade(time, operate, userId, callback) {
    bleDscpUtils.sendCmdTest(callback, DscpCode.DEVICE_UPGRADE, sendCmdData);
  }

  /**
   * 设备测试
   * timestamp
   * action: 动作
   * 1：蓝牙被动开锁
   * 2：上锁
   * 3：时间较准
   * 4：转动电机
   * 5：语音测试
   * 6: MTU测试
   */
  deviceTest(time, operateCode, callback, mtuLength) {
    let sendCmdData = new Array();
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(time));
    sendCmdData.push(operateCode);
    if (operateCode == 6 || operateCode == 7 || operateCode == 0x10) {
      sendCmdData.push(mtuLength);
    }
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let obj = new Object();
      obj.time = protocolUtils.getTimeByArray(recvCmdData.slice(0, 6));
      obj.isSucceed = recvCmdData[6] == 0;
      if (operateCode == 0x10) {
        obj.resetTime = protocolUtils.getTimeByArray(recvCmdData.slice(7, 13));
        obj.errFileName = byteUtils.ab2hex(recvCmdData.slice(13, 37), " ");
        obj.errLineNumber = byteUtils.ab2hex(recvCmdData.slice(37, 39), " ");
        console.log(obj);
      }
      callback(true, obj);
    }, DscpCode.DEVICE_TEST, sendCmdData);
  }

  /**
   * 读取Ram的内存值
   * @param {时间戳} time 
   * @param {内存地址} 4Byte address 
   * @param {内存长度} 2Byte length 
   * @param {回调结果} callback 
   */
  getDeviceRamData(time, address, length, callback) {
    let sendCmdData = new Array();
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(time), address, length);

    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      console.log("----------读取内存结果----------")
      if (!result) {
        console.log("失败")
        callback(false)
        return;
      }
      console.log(byteUtils.ab2hex(recvCmdData));
      callback(true, recvCmdData);
    }, DscpCode.GET_DEVICE_RAM_DATA, sendCmdData)
  }

  /**
   * 设备配置
   * 配置1：回锁配置
   * 设置自动回锁时间
   * @param {当前时间戳} time 
   * @param {模式：1：按时间回锁 2：不自动回锁} mode 
   * @param {回锁时间：只有回锁模式为1时有效，时间单位s秒} lockTime 
   * return 1Byte
   * 配置2：指纹配置
   * 需要记录日志的，1分钟内指纹连续未识别次数
   * 
   * 操作结果
   * 0：成功
   * 1：失败
   * 2：没有自动回锁功能
   */
  setDeviceConfig(time, config, param, callback) {
    let sendCmdData = new Array();
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(time));
    sendCmdData.push(config);
    sendCmdData = sendCmdData.concat(param);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      callback(true, (recvCmdData[0] & 0x0F) == 0, recvCmdData[0]);
    }, DscpCode.DEVICE_CONFIG, sendCmdData)
  }

  /**
   * 设置黑名单
   * 6Byte	时间戳
   * 1Byte	黑名单人数N
   * 4 * N  每四字节为一个黑名单
   * 操作结果
   * 0：成功 1：失败 2：黑名单用户过多
   */
  setBlacklist(time, number, userIdList, callback) {
    let sendCmdData = new Array();
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(time));
    // 修复设备不会覆盖黑名单的bug
    // 自动将黑名单用户长度扩展为最长长度10
    sendCmdData.push(10);
    userIdList.forEach(element => {
      sendCmdData = sendCmdData.concat(protocolUtils.getUserIdArray(element.userId));
    });
    for (let i = number; i < 10; ++i) {
      sendCmdData = sendCmdData.concat([0xff, 0xff, 0xff, 0xff]);
    }
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      callback(true, recvCmdData[0]);
    }, DscpCode.SET_BLACKLIST, sendCmdData)
  }

  /******************设备信息管理******************/

  /**
   * 获取设备信息
   * 输入参数： 无
   * 输出参数：
   * 2Byte 硬件版本号
   * 2Byte 固件版本号（软件版本号）
   * 1Byte typeCode 锁类型编码
   * 16Byte 锁类型字符串
   * 2Byte 锁功能支持
   * 4Byte 已注册：用户ID  未注册：全填0xFF
   * 1Byte 锁开关状态 0：关 1：开
   * 6Byte 设备时间戳	
   * 16Byte 设备SN
   * 1Byte 正常广播间隔（单位50ms秒）
   * 1Byte 备用字段
   * 1Byte 备用字段
   * 2Byte IP端口号
   * 1Byte IP地址的长度n
   * nByte IP地址的ASCII码字符串
   */
  getDeviceInfo(callback) {
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false)
        return;
      }
      let obj = new Object();
      obj.hardwareVersion = protocolUtils.getVersion(recvCmdData[0], recvCmdData[1]);
      obj.softwareVersion = protocolUtils.getVersion(recvCmdData[2], recvCmdData[3]);
      obj.typeCode = byteUtils.bytes2ToInt(recvCmdData.slice(4, 6));
      obj.supportFunctionBase = recvCmdData[6];
      obj.supportFunctionOther = recvCmdData[7];
      obj.userId = protocolUtils.getUserId(recvCmdData.slice(8, 12));
      obj.isLock = recvCmdData[12] == 0 ? true : false;
      obj.deviceDate = protocolUtils.getTimeByArray(recvCmdData.slice(13, 19));
      obj.sn = recvCmdData.slice(19, 35);
      obj.broadcastInterval = recvCmdData[35];
      obj.deviceSvnVersion = recvCmdData[36] & 0xff;
      obj.spare2 = recvCmdData[37];
      obj.ipPort = byteUtils.bytes2ToInt(recvCmdData.slice(38, 40));
      obj.ipLength = recvCmdData[40] & 0xff;
      if (obj.ipLength > 0) {
        obj.ip = byteUtils.bytesToAsciiStr(recvCmdData.slice(41, 41 + obj.ipLength));
      } else {
        obj.ip = "";
      }
      console.log(byteUtils.ab2hex(recvCmdData.slice(41 + obj.ipLength, 41 + obj.ipLength + 16)));
      obj.fpModel = byteUtils.bytesToAsciiStr(recvCmdData.slice(41 + obj.ipLength, 41 + obj.ipLength + 16));
      callback(true, obj)
    }, DscpCode.GET_DEVICE_INFO, null);
  }

  /**
   * 获取设备状态
   * 输入参数：时间戳
   * 输出参数：
   * 2Byte 电池电量
   * 2Byte NB信号
   * 2Byte 信噪比
   * 1Byte 锁开关状态 0关 1开
   * 1Byte 主锁锁舌开关状态 1伸出，0缩回
   * 1Byte 反锁锁体开关状态	0缩回（关），1伸出（开）
   * 1Byte 门磁开关状态
   * 1Byte 指纹已使用个数
   * 1Byte 指纹剩余可使用个数
   * 1Byte 密钥已使用个数
   * 1Byte 密码剩余可使用个数
   * 1Byte IC卡已使用个数
   * 1Byte IC卡剩余可使用个数
   * 2Byte 可存日志总数
   * 2Byte 最新日志下标
   * 6Byte 最新日志时间
   * 1Byte 回锁模式：1：按时间回锁 2：不自动回锁
   * 1Byte 回锁时间：只有回锁模式为1时有效，时间单位s秒
   */
  getDeviceStatus(date, callback) {
    let sendCmdData = new Array();
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(date))
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let obj = new Object();
      obj.electricity = protocolUtils.getPower(recvCmdData[0], recvCmdData[1]);
      obj.rsrp = protocolUtils.getSignal(recvCmdData[2], recvCmdData[3]);
      obj.sinr = protocolUtils.getSignal(recvCmdData[4], recvCmdData[5]);
      obj.isLocked = recvCmdData[6] == 0;
      obj.bolt = recvCmdData[7];
      obj.antiLock = recvCmdData[8];
      obj.doorMagnet = recvCmdData[9];
      obj.fingerprintUsed = recvCmdData[10];
      obj.fingerprintLeft = recvCmdData[11];
      obj.passwordUsed = recvCmdData[12];
      obj.passwordLeft = recvCmdData[13];
      obj.icCardUsed = recvCmdData[14];
      obj.icCardLeft = recvCmdData[15];
      obj.logMaxNumber = byteUtils.bytes2ToInt(recvCmdData.slice(16, 18));
      obj.logIndex = byteUtils.bytes2ToInt(recvCmdData.slice(18, 20));
      obj.ungetLogNumber = byteUtils.bytes2ToInt(recvCmdData.slice(20, 22));
      obj.ungetLogIndex = byteUtils.bytes2ToInt(recvCmdData.slice(22, 24));
      obj.logTime = protocolUtils.getTimeByArray(recvCmdData.slice(24, 30));
      obj.lockMode = recvCmdData[30];
      obj.lockTime = recvCmdData[31];
      callback(true, obj);
    }, DscpCode.GET_DEVICE_STATUS, sendCmdData);
  }

  /**
   * 获取设备日志
   * 输入参数：
   * index 需要获取的日志的下标 2Byte
   * 输出参数：
   * 4Byte 用户ID
   * 6Byte 开锁时间
   * 1Byte 操作方式 0：蓝牙开锁 1：蓝牙上锁 2：指纹开锁
   *        3：刷卡开锁 4：密码开锁 5：钥匙开锁
   * 1Byte 操作类型 1：开锁 2：上锁
   * 1Byte 操作结果 0：成功 1：认证失败 2：操作错误
   * 12Byte 开锁类型 1：指纹ID 2：磁卡ID 3：密码
   * 7Byte 备用字段
   */
  getDeviceLog(index, callback) {
    let sendCmdData = new Array();
    sendCmdData = sendCmdData.concat(byteUtils.intToBytes2(index));
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let obj = new Object();
      obj.index = byteUtils.bytes2ToInt(recvCmdData.slice(0, 2));
      obj.totalIndex = byteUtils.bytes2ToInt(recvCmdData.slice(2, 4));
      obj.userId = protocolUtils.getUserId(recvCmdData.slice(4, 8));
      obj.time = protocolUtils.getTimeByArray(recvCmdData.slice(8, 14));
      obj.operateWay = recvCmdData[14];
      obj.operateResult = recvCmdData[15];
      console.log("recvCmdData[16] = " + recvCmdData[16]);
      // obj.isUpload = recvCmdData[15] != 0xff; 0xff转换后默认等于-1;
      obj.isUploaded = recvCmdData[16] != -1;
      // 13 - 25字节（不包含25）
      switch (obj.operateWay) {
        case 0:
          console.log("蓝牙开锁日志")
          break;
        case 1:
          console.log("蓝牙上锁日志")
          break;
        case 2:
          obj.fpId = recvCmdData[17];
          break;
        case 3:
          obj.icCardId = recvCmdData.slice(17, 29);
          break;
        case 4:
          obj.pwd = recvCmdData.slice(17, 23);
          break;
        default:
          console.log("操作方式获取错误---不包含ID" + obj.operateWay)
      }
      // 7 Byte 备用字段
      callback(true, obj);
    }, DscpCode.GET_DEVICE_LOG, sendCmdData);
  }

  /******************指纹管理******************/
  /**
   * 添加设备内指纹
   * 输入参数：
   * timestamp 时间戳
   * userId 用户Id
   * fingerId 手指编号 1Byte
   * fpMode  指纹开锁模式：1：指纹模式 2：指纹+蓝牙模式
   * isFreeze 是否冻结 1byte 0冻结 1启用 2删除
   * limitCount 有效次数 1Byte
   * useTimeControl 启用时间控制 1启用 0不启用
   * startTime 生效时间戳
   * endTime 失效时间戳
   * everyWeek 每周生效时间 1byte
   * dayStartTime 每日生效时间 2byte
   * dayEndTime 每日失效时间 2byte
   * 输出参数：
   * succeed  0:成功 1:失败 2:硬件不支持 3：指纹已存在  1byte
   * fpId 指纹ID 1byte
   */
  addDeviceFp(date, userId, fingerId, fpMode, isFreeze, limitCount,
    useTimeControl, startTime, endTime, everyWeek, dayStartTime, dayEndTime
    , callback) {
    let sendCmdData = new Array();
    let timestamp = protocolUtils.getTimeArray(date);
    let userIdArray = protocolUtils.getUserIdArray(userId);
    sendCmdData = sendCmdData.concat(timestamp, userIdArray);
    if (fingerId > 0 && fingerId <= 10) {
      sendCmdData.push(fingerId);
    }
    sendCmdData.push(fpMode);
    sendCmdData.push(isFreeze);
    sendCmdData.push(limitCount);
    sendCmdData.push(useTimeControl);
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(startTime),
      protocolUtils.getTimeArray(endTime));
    sendCmdData.push(everyWeek)
    sendCmdData = sendCmdData.concat(dayStartTime, dayEndTime);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      callback(true, recvCmdData[0]);
    }, DscpCode.ADD_DEVICE_FP, sendCmdData);
  }

  /**
   * 接收到指纹录入状态的回应
   */
  responseRecvFp(responseCode) {
    let sendCmdData = new Array();
    sendCmdData.push(responseCode);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      console.log("应该无回应------")
      if (!result) {
        console.warn("发送指纹录入状态响应失败")
      }
      console.warn("发送指纹录入状态响应成功")
    }, DscpCode.RECEIVE_FP_ADD_STATUS, sendCmdData);
  }

  /**
   * 提取指纹特征
   * 输入参数
   * 指纹数据上传请求类型
   * UpFlag==0x02时，N=指纹ID（1byte），指纹包序号（1byte）（重传也用该指令）； 
   * UpFlag==0x03。N=指纹ID（1byte），操作结果（1byte，0x00表示成功；0x01表示失败）；
   */
  getFpFeature(upFlag, fpId, fpPackageIndex, getResult, callback) {
    let sendCmdData = new Array();
    sendCmdData.push(upFlag);
    sendCmdData.push(fpId);
    switch (upFlag) {
      case 1:
        break;
      case 2:
        sendCmdData.push(fpPackageIndex);
        break;
      case 3:
        sendCmdData.push(getResult);
        break;
      case 4:
        break;
    }
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      callback(true, recvCmdData);
    }, DscpCode.GET_FP_FEATURE, sendCmdData);
  }

  /********************* 写入指纹特征 ***********************/
  /**
   * 开始写入指纹特征
   * @param {*} packageNumber 包数量 
   * @param {*} bytesNumber 特征值字节数
   * @param {*} userId 用户ID
   * 
   */
  setFpFeatureStart(packageNumber, bytesNumber, fpModel, userId, fingerId, fpMode,
    isFreeze, limitCount, useTimeControl, startTime, endTime,
    everyWeek, dayStartTime, dayEndTime, callback) {
    let sendCmdData = new Array();
    sendCmdData.push(packageNumber);
    sendCmdData = sendCmdData.concat(byteUtils.intToBytes2(bytesNumber));
    sendCmdData = sendCmdData.concat(byteUtils.strToAsciiBytes(fpModel));
    sendCmdData = sendCmdData.concat(protocolUtils.getUserIdArray(userId));
    sendCmdData.push(fingerId);
    sendCmdData.push(fpMode);
    sendCmdData.push(isFreeze);
    sendCmdData.push(limitCount);
    sendCmdData.push(useTimeControl);
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(startTime),
      protocolUtils.getTimeArray(endTime));
    sendCmdData.push(everyWeek)
    sendCmdData = sendCmdData.concat(dayStartTime, dayEndTime);
    this._setFpFeature(0x01, sendCmdData, callback);
  }

  setFpFeaturePackage(fpId, packageIndex, values, callback) {
    let sendCmdData = new Array();
    sendCmdData.push(fpId, packageIndex);
    sendCmdData.push(values.length);
    sendCmdData = sendCmdData.concat(values);
    this._setFpFeature(0x02, sendCmdData, callback);
  }

  setFpFeatureEnd(fpId, callback) {
    let sendCmdData = new Array();
    sendCmdData.push(fpId);
    this._setFpFeature(0x03, sendCmdData, callback);
  }

  setFpFeatureError(fpId, callback) {
    let sendCmdData = new Array();
    sendCmdData.push(fpId);
    this._setFpFeature(0x04, sendCmdData, callback);
  }

  _setFpFeature(upFlag, data, callback) {
    let sendCmdData = new Array();
    sendCmdData.push(upFlag);
    sendCmdData = sendCmdData.concat(data);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      callback(true, recvCmdData);
    }, DscpCode.SET_FP_FEATURE, sendCmdData);
  }

  /**
   * 获取设备内指纹列表
   * 输入参数：
   * 1Byte 指纹下标
   * 说明：获取设备状态时可以获取到指纹的已用个数N，指纹下标
   * index的值为0到N-1。由设备自己维护，不同index返回不同的指纹值
   * 输出参数：
   * 1Byte 指纹下标
   * 4Byte 用户ID
   * 1Byte 指纹ID
   * 1Byte 是否冻结 0冻结 1启用 2删除
   * 1Byte 有效次数 0xFF表示无限制
   * 1Byte 启用时间控制 1启用 0不启用
   * 6Byte 生效开始时间戳
   * 6Byte 生效结束时间戳
   * 1Byte 每周生效时间
   * 2Byte 每日生效开始时间 时-分
   * 2Byte 每日生效结束时间
   */
  getFpList(index, callback) {
    let sendCmdData = new Array();
    sendCmdData.push(index)
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let obj = new Object();
      obj.index = recvCmdData[0];
      obj.fpId = recvCmdData[1];
      obj.intUserId = protocolUtils.getUserId(recvCmdData.slice(2, 6));
      if ((recvCmdData[8] & 0xff) == 0xff) {
        obj.fpMode = recvCmdData[6]
        obj.isFreeze = recvCmdData[7] == 0;
        obj.limitCount = recvCmdData[8];
        obj.isUseTimeControl = recvCmdData[9] == 1;
        obj.startTime = protocolUtils.getTimeByArray(recvCmdData.slice(10, 16));
        obj.endTime = protocolUtils.getTimeByArray(recvCmdData.slice(16, 22));
        obj.everyWeek = recvCmdData[22];
        obj.dayStartTimeHour = recvCmdData[23];
        obj.dayStartTimeMinute = recvCmdData[24];
        obj.dayEndTimeHour = recvCmdData[25];
        obj.dayEndTimeMinute = recvCmdData[26];
      } else {
        obj.fingerId = recvCmdData[6];
        obj.fpMode = recvCmdData[7]
        obj.isFreeze = recvCmdData[8] == 0;
        obj.limitCount = recvCmdData[9];
        obj.isUseTimeControl = recvCmdData[10] == 1;
        obj.startTime = protocolUtils.getTimeByArray(recvCmdData.slice(11, 17));
        obj.endTime = protocolUtils.getTimeByArray(recvCmdData.slice(17, 23));
        obj.everyWeek = recvCmdData[23];
        obj.dayStartTimeHour = recvCmdData[24];
        obj.dayStartTimeMinute = recvCmdData[25];
        obj.dayEndTimeHour = recvCmdData[26];
        obj.dayEndTimeMinute = recvCmdData[27];
      }
      callback(true, obj);
    }, DscpCode.GET_FP_LIST, sendCmdData);
  }

  /**
   * 清空设备内指纹列表
   * 输入参数：
   * 6Byte 时间戳
   * 输出参数：
   * 1Byte 0成功 1失败
   */
  clearFpList(date, callback) {
    let sendCmdData = new Array();
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(date))
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let isSucceed = ((recvCmdData[0] & 0x0F) == 0);
      callback(true, isSucceed);
    }, DscpCode.CLEAR_FP_LIST, sendCmdData);
  }

  /**
   * 修改设备内指纹
   * 输入参数：
   * timestamp 时间戳
   * userId 用户Id
   * fpId 指纹Id
   * isFreeze 是否冻结 1byte 0冻结 1启用 2删除
   * limitCount 有效次数 1Byte
   * useTimeControl 启用时间控制 1启用 0不启用
   * startTime 生效时间戳
   * endTime 失效时间戳
   * everyWeek 每周生效时间 1byte
   * dayStartTime 每日生效时间 2byte
   * dayEndTime 每日失效时间 2byte
   * 输出参数：
   * succeed  0:成功 1:失败 2:硬件不支持 3：指纹已存在  1byte
   */
  modifyFp(date, userId, fingerId, fpMode, fpId, isFreeze, limitCount,
    useTimeControl, startTime, endTime, everyWeek, dayStartTime, dayEndTime
    , callback) {
    let sendCmdData = new Array();
    let timestamp = protocolUtils.getTimeArray(date)
    let userIdArray = protocolUtils.getUserIdArray(userId)
    sendCmdData = sendCmdData.concat(timestamp)
    sendCmdData.push(fpId)
    sendCmdData = sendCmdData.concat(userIdArray);
    if (fingerId > 0 && fingerId <= 10) {
      sendCmdData.push(fingerId);
    }
    sendCmdData.push(fpMode)
    sendCmdData.push(isFreeze)
    sendCmdData.push(limitCount)
    sendCmdData.push(useTimeControl)
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(startTime),
      protocolUtils.getTimeArray(endTime));
    sendCmdData.push(everyWeek)
    sendCmdData = sendCmdData.concat(dayStartTime, dayEndTime);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let isSucceed = ((recvCmdData[0] & 0x0F) == 0);
      callback(true, isSucceed);
    }, DscpCode.MODIFY_FP, sendCmdData);
  }

  /******************IC卡接口管理******************/
  /**
   * 添加设备内IC卡
   * 输入参数：
   * timestamp 时间戳
   * userId 用户Id
   * isFreeze 是否冻结 1byte 0冻结 1启用 2删除
   * limitCount 有效次数 1Byte
   * useTimeControl 启用时间控制 1启用 0不启用
   * startTime 生效时间戳
   * endTime 失效时间戳
   * everyWeek 每周生效时间 1byte
   * dayStartTime 每日生效时间 2byte
   * dayEndTime 每日失效时间 2byte
   * 输出参数：
   * succeed  0:成功 1:失败 2:硬件不支持
   */
  addDeviceIcCard(date, userId, mode, icCardNumber, isFreeze, limitCount,
    useTimeControl, startTime, endTime, everyWeek, dayStartTime, dayEndTime
    , callback) {
    let sendCmdData = new Array();
    let timestamp = protocolUtils.getTimeArray(date);
    let userIdArray = protocolUtils.getUserIdArray(userId);
    sendCmdData = sendCmdData.concat(timestamp, userIdArray);
    sendCmdData.push(mode);
    sendCmdData = sendCmdData.concat(byteUtils.strToAsciiBytes(icCardNumber));
    sendCmdData.push(isFreeze);
    sendCmdData.push(limitCount);
    sendCmdData.push(useTimeControl);
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(startTime),
      protocolUtils.getTimeArray(endTime));
    sendCmdData.push(everyWeek)
    sendCmdData = sendCmdData.concat(dayStartTime, dayEndTime);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let isSucceed = ((recvCmdData[0] & 0x0F) == 0);
      callback(true, isSucceed);
    }, DscpCode.ADD_DEVICE_ICCARD, sendCmdData);
  }

  /**
   * 获取设备内IC卡列表
   * 输入参数：
   * 6Byte 时间戳
   * 1Byte IC卡下标
   * 输出参数：
   * 1Byte IC卡下标
   * 4Byte 用户ID
   * 12Byte 磁卡ID
   * 1Byte 是否冻结 0冻结 1启用 2删除
   * 1Byte 有效次数 0xFF表示无限制
   * 1Byte 启用时间控制 1启用 0不启用
   * 6Byte 生效开始时间戳
   * 6Byte 生效结束时间戳
   * 1Byte 每周生效时间
   * 2Byte 每日生效开始时间 时-分
   * 2Byte 每日生效结束时间
   */
  getIcCardList(index, callback) {
    let sendCmdData = new Array();
    sendCmdData.push(index);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let obj = new Object();
      obj.index = recvCmdData[0];
      obj.userId = recvCmdData.slice(1, 5);
      obj.fpId = recvCmdData[5];
      obj.isFreeze = recvCmdData[6] == 0;
      obj.limitCount = recvCmdData[7];
      obj.isUseTimeControl = recvCmdData[8] == 1;
      obj.startTime = protocolUtils.getTimeByArray(recvCmdData.slice(9, 15))
      obj.endTime = protocolUtils.getTimeByArray(recvCmdData.slice(15, 21))
      obj.everyWeek = recvCmdData[21]
      obj.dayStartTimeHour = recvCmdData[22]
      obj.dayStartTimeMinute = recvCmdData[23]
      obj.dayEndTimeHour = recvCmdData[24]
      obj.dayEndTimeMinute = recvCmdData[25]
      console.log(obj)
      callback(true, obj);
    }, DscpCode.GET_ICCARD_LIST, sendCmdData);
  }

  /**
   * 清空设备内IC卡列表
   * 输入参数：
   * 6Byte 时间戳
   * 输出参数：
   * 1Byte 0成功 1失败
   */
  clearIcCardList(date, callback) {
    let sendCmdData = new Array();
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(date))
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let isSucceed = recvCmdData[0] == 0;
      callback(result, isSucceed)
    }, DscpCode.CLEAR_ICCARD_LIST, sendCmdData);
  }

  /**
   * 修改设备内IC卡
   * 输入参数：
   * timestamp 时间戳
   * userId 用户Id
   * isFreeze 是否冻结 1byte 0冻结 1启用 2删除
   * limitCount 有效次数 1Byte
   * useTimeControl 启用时间控制 1启用 0不启用
   * startTime 生效时间戳
   * endTime 失效时间戳
   * everyWeek 每周生效时间 1byte
   * dayStartTime 每日生效时间 2byte
   * dayEndTime 每日失效时间 2byte
   * 输出参数：
   * succeed  0:成功 1:失败 2:硬件不支持
   */
  modifyIcCard(date, userId, icCardId, isFreeze, limitCount,
    useTimeControl, startTime, endTime, everyWeek, dayStartTime, dayEndTime
    , callback) {
    let sendCmdData = new Array();
    let timestamp = protocolUtils.getTimeArray(date)
    let userIdArray = protocolUtils.getUserIdArray(userId);
    let icCardArray = byteUtils.strToAsciiBytes(icCardId);
    sendCmdData = sendCmdData.concat(timestamp, userIdArray, icCardArray);
    sendCmdData.push(isFreeze)
    sendCmdData.push(limitCount)
    sendCmdData.push(useTimeControl)
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(startTime),
      protocolUtils.getTimeArray(endTime));
    sendCmdData.push(everyWeek)
    sendCmdData = sendCmdData.concat(dayStartTime, dayEndTime);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let isSucceed = recvCmdData[0] == 0;
      callback(true, isSucceed);
    }, DscpCode.MODIFY_ICCARD, sendCmdData);
  }

  /******************密码接口管理******************/
  /**
   * 添加设备内密码
   * 输入参数：
   * timestamp 时间戳
   * userId 用户Id
   * 6Byte 密码
   * isFreeze 是否冻结 1byte 0冻结 1启用 2删除
   * limitCount 有效次数 1Byte
   * useTimeControl 启用时间控制 1启用 0不启用
   * startTime 生效时间戳
   * endTime 失效时间戳
   * everyWeek 每周生效时间 1byte
   * dayStartTime 每日生效时间 2byte
   * dayEndTime 每日失效时间 2byte
   * 输出参数：
   * succeed  0:成功 1:失败 2:硬件不支持 3:密码已存在
   */
  addDevicePassword(date, userId, password, isFreeze, limitCount,
    useTimeControl, startTime, endTime, everyWeek, dayStartTime, dayEndTime
    , callback) {
    let sendCmdData = new Array();
    let timestamp = protocolUtils.getTimeArray(date);
    let userIdArray = protocolUtils.getUserIdArray(userId);
    let pwd = byteUtils.strToAsciiBytes(password);
    sendCmdData = sendCmdData.concat(timestamp, userIdArray, pwd);
    sendCmdData.push(isFreeze)
    sendCmdData.push(limitCount)
    sendCmdData.push(useTimeControl)
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(startTime),
      protocolUtils.getTimeArray(endTime));
    sendCmdData.push(everyWeek)
    sendCmdData = sendCmdData.concat(dayStartTime, dayEndTime);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let isSucceed = (recvCmdData[0] & 0x0F) == 0;
      callback(true, isSucceed, recvCmdData[0]);
    }, DscpCode.ADD_DEVICE_PASSWORD, sendCmdData);
  }

  /**
   * 添加设备内密码
   * 输入参数：
   * 6Byte 时间戳
   * 1Byte 密码下标
   * 输出参数：
   * 1Byte 密码下标
   * userId 用户Id
   * 6Byte 密码
   * isFreeze 是否冻结 1byte 0冻结 1启用 2删除
   * limitCount 有效次数 1Byte
   * useTimeControl 启用时间控制 1启用 0不启用
   * startTime 生效时间戳
   * endTime 失效时间戳
   * everyWeek 每周生效时间 1byte
   * dayStartTime 每日生效时间 2byte
   * dayEndTime 每日失效时间 2byte
   */
  getPasswordList(index, callback) {
    let sendCmdData = new Array();
    sendCmdData.push(index);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let obj = new Object();
      obj.index = recvCmdData[0];
      obj.userId = recvCmdData.slice(1, 5);
      obj.password = byteUtils.bytesToAsciiStr(recvCmdData.slice(5, 11));
      obj.isFreeze = recvCmdData[11] == 0;
      obj.limitCount = recvCmdData[12];
      obj.isUseTimeControl = recvCmdData[13] == 1;
      obj.startTime = protocolUtils.getTimeByArray(recvCmdData.slice(13, 19))
      obj.endTime = protocolUtils.getTimeByArray(recvCmdData.slice(19, 25))
      obj.everyWeek = recvCmdData[25]
      obj.dayStartTimeHour = recvCmdData[26]
      obj.dayStartTimeMinute = recvCmdData[27]
      obj.dayEndTimeHour = recvCmdData[28]
      obj.dayEndTimeMinute = recvCmdData[29]
      console.log(obj)
      callback(true, obj);
    }, DscpCode.GET_PASSWORD_LIST, sendCmdData);
  }

  /**
   * 清空设备内密码
   * 输入参数：
   * 6Byte 时间戳
   * 输出参数：
   * 1Byte 0成功 1失败
   */
  clearPasswordList(date, callback) {
    let sendCmdData = new Array();
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(date))
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let isSucceed = (recvCmdData[0] & 0x0F) == 0;
      callback(true, isSucceed, recvCmdData[0]);
    }, DscpCode.CLEAR_PASSWORD_LIST, sendCmdData);
  }

  /**
   * 修改设备内密码
   * timestamp 时间戳
   * userId 用户Id
   * 6Byte 密码
   * isFreeze 是否冻结 1byte 0冻结 1启用 2删除
   * limitCount 有效次数 1Byte
   * useTimeControl 启用时间控制 1启用 0不启用
   * startTime 生效时间戳
   * endTime 失效时间戳
   * everyWeek 每周生效时间 1byte
   * dayStartTime 每日生效时间 2byte
   * dayEndTime 每日失效时间 2byte
   * 输出参数：
   * succeed  0:成功 1:失败 2:硬件不支持 3:密码已存在
   */
  modifyPassword(date, userId, password, isFreeze, limitCount,
    useTimeControl, startTime, endTime, everyWeek, dayStartTime, dayEndTime
    , callback) {
    let sendCmdData = new Array();
    let timestamp = protocolUtils.getTimeArray(date)
    let userIdArray = protocolUtils.getUserIdArray(userId)
    let pwd = byteUtils.strToAsciiBytes(password);
    sendCmdData = sendCmdData.concat(timestamp, userIdArray, pwd);
    sendCmdData.push(isFreeze)
    sendCmdData.push(limitCount)
    sendCmdData.push(useTimeControl)
    sendCmdData = sendCmdData.concat(protocolUtils.getTimeArray(startTime),
      protocolUtils.getTimeArray(endTime));
    sendCmdData.push(everyWeek)
    sendCmdData = sendCmdData.concat(dayStartTime, dayEndTime);
    bleDscpUtils.sendCmdTest((result, recvCmdData) => {
      if (!result) {
        callback(false);
        return;
      }
      let isSucceed = (recvCmdData[0] & 0x0F) == 0;
      callback(true, isSucceed, recvCmdData[0]);
    }, DscpCode.MODIFY_PASSWORD, sendCmdData);
  }
}

export {
  PersonalLockOperate
}